#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "BehavioredClassifier.h"
#include "Classifier.h"
#include "EncapsulatedClassifier.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Classifier;
class Extension;
class Operation;
class Property;
class Reception;

/// <summary>
/// Class
/// A Class classifies a set of objects and specifies the features that characterize
/// the structure and behavior of those objects.  A Class may have an internal
/// structure and Ports.
/// 
/// </summary>
class UMLMODEL_EXPORT Class : public Classifier, public BehavioredClassifier, public EncapsulatedClassifier {

public: // Constructors and destructors
    explicit Class(const QString& umlType="uml::Class");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
public: // Properties
    /// <summary>
    /// extensions getter
    /// This property is used when the Class is acting as a metaclass. It references the
    /// Extensions that specify additional properties of the metaclass. The property is
    /// derived from the Extensions whose memberEnds are typed by the Class.
    /// </summary>
    vector<shared_ptr<Extension>>& extensions();

    /// <summary>
    /// isAbstract getter
    /// If true, the Class does not provide a complete declaration and cannot be
    /// instantiated. An abstract Class is typically used as a target of Associations or
    /// Generalizations.
    /// </summary>
    bool isAbstract() const;

    /// <summary>
    /// isAbstract setter
    /// If true, the Class does not provide a complete declaration and cannot be
    /// instantiated. An abstract Class is typically used as a target of Associations or
    /// Generalizations.
    /// </summary>
    void setIsAbstract(bool value);

    /// <summary>
    /// isActive getter
    /// Determines whether an object specified by this Class is active or not. If true,
    /// then the owning Class is referred to as an active Class. If false, then such a
    /// Class is referred to as a passive Class.
    /// </summary>
    bool isActive() const;

    /// <summary>
    /// isActive setter
    /// Determines whether an object specified by this Class is active or not. If true,
    /// then the owning Class is referred to as an active Class. If false, then such a
    /// Class is referred to as a passive Class.
    /// </summary>
    void setIsActive(bool value);

    /// <summary>
    /// nestedClassifiers getter
    /// The Classifiers owned by the Class that are not ownedBehaviors.
    /// </summary>
    vector<shared_ptr<Classifier>>& nestedClassifiers();

    /// <summary>
    /// ownedAttributes getter
    /// The attributes (i.e., the Properties) owned by the Class.
    /// </summary>
    vector<shared_ptr<Property>>& ownedAttributes();

    /// <summary>
    /// ownedOperations getter
    /// The Operations owned by the Class.
    /// </summary>
    vector<shared_ptr<Operation>>& ownedOperations();

    /// <summary>
    /// ownedReceptions getter
    /// The Receptions owned by the Class.
    /// </summary>
    vector<shared_ptr<Reception>>& ownedReceptions();

    /// <summary>
    /// superClasses getter
    /// The superclasses of a Class, derived from its Generalizations.
    /// </summary>
    vector<shared_ptr<Class>>& superClasses();

private: // Fields
    /// <summary>
    /// extensions
    /// This property is used when the Class is acting as a metaclass. It references the
    /// Extensions that specify additional properties of the metaclass. The property is
    /// derived from the Extensions whose memberEnds are typed by the Class.
    /// </summary>
    vector<shared_ptr<Extension>> extensions_;

    /// <summary>
    /// isAbstract
    /// If true, the Class does not provide a complete declaration and cannot be
    /// instantiated. An abstract Class is typically used as a target of Associations or
    /// Generalizations.
    /// </summary>
    const static bool isAbstract_default_;
    bool isAbstract_= isAbstract_default_;

    /// <summary>
    /// isActive
    /// Determines whether an object specified by this Class is active or not. If true,
    /// then the owning Class is referred to as an active Class. If false, then such a
    /// Class is referred to as a passive Class.
    /// </summary>
    const static bool isActive_default_;
    bool isActive_= isActive_default_;

    /// <summary>
    /// nestedClassifiers
    /// The Classifiers owned by the Class that are not ownedBehaviors.
    /// </summary>
    vector<shared_ptr<Classifier>> nestedClassifiers_;

    /// <summary>
    /// ownedAttributes
    /// The attributes (i.e., the Properties) owned by the Class.
    /// </summary>
    vector<shared_ptr<Property>> ownedAttributes_;

    /// <summary>
    /// ownedOperations
    /// The Operations owned by the Class.
    /// </summary>
    vector<shared_ptr<Operation>> ownedOperations_;

    /// <summary>
    /// ownedReceptions
    /// The Receptions owned by the Class.
    /// </summary>
    vector<shared_ptr<Reception>> ownedReceptions_;

    /// <summary>
    /// superClasses
    /// The superclasses of a Class, derived from its Generalizations.
    /// </summary>
    vector<shared_ptr<Class>> superClasses_;

};

} // namespace uml
